1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2014 Devisualization (Richard Andrew Cattermole)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 module devisualization.window.context.direct3d;
25 
26 version(Have_directx_d) {
27 	import devisualization.window.window;
28 	import devisualization.window.interfaces.context;
29 
30 	class Direct3dContext : IContext {
31 		import devisualization.image.image;
32 		import winapi = windows;
33 		import directx.d3d11;
34 
35 		private {
36 			winapi.HWND hWnd;
37 			Window window;
38 
39 			ID3D11Device dev;
40 			ID3D11DeviceContext devcon;
41 			IDXGISwapChain swapchain;
42 			ID3D11RenderTargetView backbuffer;
43 		}
44 		
45 		this(Window window, WindowConfig config) {
46 			this.window = window;
47 			hWnd = window.hwnd;
48 
49 			init();
50 		}
51 		
52 		@property {
53 			void activate() {}
54 
55 			void destroy() {
56 				swapchain.Release();
57 				backbuffer.Release();
58 				dev.Release();
59 				devcon.Release();
60 			}
61 
62 			void swapBuffers() {
63 				swapchain.Present(0, 0);
64 			}
65 			
66 			WindowContextType type() { return WindowContextType.Direct3D; }
67 
68 			string toolkitVersion() {
69 				import std.conv : text;
70 				return text(devcon.GetType) ~ " " ~ text(dev.GetFeatureLevel());
71 			}
72 
73 			string shadingLanguageVersion() {
74 				switch(dev.GetFeatureLevel()) {
75 					case D3D_FEATURE_LEVEL_9_1:
76 					case D3D_FEATURE_LEVEL_9_2:
77 						return "2";
78 					case D3D_FEATURE_LEVEL_9_3:
79 						return "2.0b";
80 					case D3D_FEATURE_LEVEL_10_0:
81 					case D3D_FEATURE_LEVEL_10_1:
82 						return "4";
83 					case D3D_FEATURE_LEVEL_11_0:
84 						return "5";
85 					//case D3D_FEATURE_LEVEL_11_1:
86 					//	return "5 with logical blend operations";
87 
88 					default:
89 						return null;
90 				}
91 			}
92 
93 			ID3D11Device device() { return dev; }
94 			ID3D11DeviceContext deviceContext() { return devcon; }
95 			IDXGISwapChain swapChain() { return swapchain; }
96 			ID3D11RenderTargetView backBuffer() { return backbuffer; }
97 		}
98 
99 		private {
100 			void init() {
101 				import std.c..string : memset;
102 
103 				// create a struct to hold information about the swap chain
104 				DXGI_SWAP_CHAIN_DESC scd;
105 				
106 				// clear out the struct for use
107 				memset(&scd, 0, DXGI_SWAP_CHAIN_DESC.sizeof );
108 				
109 				// fill the swap chain description struct
110 				scd.BufferCount = 1;                                    // one back buffer
111 				scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
112 				scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
113 				scd.OutputWindow = hWnd;                                // the window to be used
114 				scd.SampleDesc.Count = 4;                               // how many multisamples
115 				scd.Windowed = true;                                    // windowed/full-screen mode
116 				
117 				// create a device, device context and swap chain using the information in the scd struct
118 				D3D11CreateDeviceAndSwapChain(null,
119 					D3D_DRIVER_TYPE_HARDWARE,
120 					null,
121 					0,
122 					null,
123 					0,
124 					D3D11_SDK_VERSION,
125 					&scd,
126 					&swapchain,
127 					&dev,
128 					null,
129 					&devcon);
130 				
131 				// get the address of the back buffer
132 				ID3D11Texture2D pBackBuffer;
133 				swapchain.GetBuffer(0, &IID_ID3D11Texture2D, cast(void**)&pBackBuffer);
134 				
135 				// use the back buffer address to create the render target
136 				dev.CreateRenderTargetView(pBackBuffer, null, &backbuffer);
137 				pBackBuffer.Release();
138 				
139 				// set the render target as the back buffer
140 				devcon.OMSetRenderTargets(1, &backbuffer, null);
141 
142 				winapi.RECT winsize;
143 				winapi.GetClientRect(hWnd, &winsize);
144 
145 				// Set the viewport
146 				D3D11_VIEWPORT viewport;
147 				memset(&viewport, 0, D3D11_VIEWPORT.sizeof);
148 				
149 				viewport.TopLeftX = 0;
150 				viewport.TopLeftY = 0;
151 				viewport.Width = winsize.right;
152 				viewport.Height = winsize.bottom;
153 				
154 				devcon.RSSetViewports(1, &viewport);
155 			}
156 		}
157 	}
158 }